#pragma once

#include "ComponentsPrereq.h"

namespace ne{
class GameObject;
class CameraComponent : public Component {
public:
	CameraComponent();
	virtual ~CameraComponent();

	void Init();
	void SetFarClipDistance(float farClip) {m_camera->setFarClipDistance(farClip);}
	void SetNearClipDistance(float nearClip) {m_camera->setNearClipDistance(nearClip);}
	virtual void Shut();
	virtual luabind::object GetAsLua(lua_State* L) {return luabind::object(L,this);}
	void SetPosition(float x,float y,float z);
	void SetPosition(const Ogre::Vector3& pos);
	Ogre::Vector3 GetPosition()const;
	Ogre::Vector3 GetDerivedPosition()const;
	Ogre::Vector3 GetDirection();
	Ogre::Quaternion GetOrientation(){return m_camera->getOrientation();}

protected:
	static int s_counter;
	Ogre::Camera* m_camera;
	Ogre::SceneNode* m_cameraNode;
	Ogre::SceneManager* m_sceneManager;
};

class InputSystem;
class FirstPersonCameraComponent : public CameraComponent, public IComponentUpdate {
public:
	FirstPersonCameraComponent();
	virtual ~FirstPersonCameraComponent(){}

	void Init();
	void SetRotationSpeed(float value){m_rotSpeed=value;}
	void SetMovementSpeed(float value){m_movementSpeed=value;}
	void LimitAngle(bool value){m_limit=value;}
	void SetForward(int key){m_forward=key;}
	void SetBackward(int key){m_backward=key;}
	void SetLeft(int key){m_left=key;}
	void SetRight(int key){m_right=key;}
	void SetUp(int key){m_up=key;}
	void SetDown(int key){m_down=key;}
	void EnableControl(bool value){m_control=value;}

	void Update(GameTime* gameTime);
	luabind::object GetAsLua(lua_State* L){return luabind::object(L,this);}
private:
	InputSystem*	 m_inputSystem;
	Ogre::Vector3	 m_translation;
	Ogre::Radian	 m_pitch;
	Ogre::Radian	 m_yaw;
	float			 m_rotSpeed;
	float			 m_movementSpeed;
	Ogre::Degree	 m_pitchLimit;
	bool			 m_limit;
	bool			 m_control;
	int				 m_forward;
	int				 m_backward;
	int				 m_left;
	int				 m_right;
	int				 m_up;
	int				 m_down;
};

class ThirdPersonCameraComponent : public CameraComponent,public IComponentUpdate{
public:
	ThirdPersonCameraComponent();
	virtual ~ThirdPersonCameraComponent();
	void Init();
	void SetTarget(Ogre::SceneNode* p_target){m_target=p_target;}	// This function will be called from LUA script
	void Update(GameTime* gameTime);
	virtual luabind::object GetAsLua(lua_State* L) {return luabind::object(L,this);}
	Ogre::Vector3 GetDirectionFromCamera(Ogre::Vector3 p_dir);
	Ogre::Quaternion GetCameraOrientation()const{return m_cameraPivot->getOrientation();}
	void SetPitchLimit(float p_pitchLimit){m_pitchLimit=p_pitchLimit;}
	void SetHorizontalSpeed(float p_horSpeed){m_horSpeed=p_horSpeed;}
	void SetVerticalInvert(bool p_value);
	bool IsVerticalInvert()const;
	bool IsHorizontalInvert()const;
	void SetHorizontalInvert(bool p_value);
	void SetCameraInvert(bool p_value);
	void SetVerticalSpeed(float p_verSpeed){m_verSpeed=p_verSpeed;}
	void SetCameraSpeed(float p_cameraSpeed){m_verSpeed=p_cameraSpeed;m_horSpeed=p_cameraSpeed;}
	void SetZoomSpeed(float p_zoomSpeed){m_zoomSpeed=p_zoomSpeed;}
	void SetMinZoomDistance(float p_minZoomDist){m_minZoomDist=p_minZoomDist;}
	void SetMaxZoomDistance(float p_maxZoomDist){m_maxZoomDist=p_maxZoomDist;}
	float GetMinZoomDistance()const{return m_minZoomDist;}
	float GetMaxZoomDistance()const{return m_maxZoomDist;}
	float GetVerticalSpeed()const{return m_verSpeed;}
	float GetHorizontalSpeed()const{return m_horSpeed;}

private:
	void UpdateCameraGoal(float p_deltaYaw,float p_deltaPitch,float p_deltaZoom);

	Ogre::SceneNode*	m_cameraPivot;
	Ogre::SceneNode*	m_target;
	InputSystem*		m_inputSystem;
	Ogre::Radian		m_yaw;
	Ogre::Radian		m_pitch;
	Ogre::Degree		m_pitchLimit;
	float				m_horSpeed;		// rotation speed for horizontal camera movement
	float				m_verSpeed;		// rotation speed for vertical camera movement
	float				m_pivotPitch;
	float				m_cameraHeight;
	int					m_horInvert;
	int					m_verInvert;
	float				m_zoomSpeed;
	float				m_minZoomDist;
	float				m_maxZoomDist;
};

}